package payment

import (
	"cloud_android_backend/pkg/models/orders"
	"cloud_android_backend/pkg/models/products"
	"cloud_android_backend/pkg/models/resources"
	user "cloud_android_backend/pkg/models/users"
	"cloud_android_backend/pkg/modules/instances"
	"cloud_android_backend/pkg/modules/realphone"
	"encoding/json"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/golang/glog"
	"github.com/jinzhu/gorm"
	"github.com/smartwalle/alipay/v3"
	"modules.tenxcloud.com/common/composite"
	"strconv"
	"time"
)

func AlipayCallback(c *gin.Context) error {
	transaction, err := AlipayClient.GetTradeNotification(c.Request)
	if err != nil {
		//c.JSON(http.StatusBadRequest, gin.H{
		//	"error": "解析通知失败: " + err.Error(),
		//})
		glog.Errorf("解析通知失败: %v", err)
		return err
	}
	transactionJson, err := json.Marshal(transaction)
	if err != nil {
		fmt.Printf("marshall transaction json failed:%v\n", err)
		//return err
	}
	fmt.Printf("alipay支付回调返回transaction：%s\n", string(transactionJson))

	db, err := composite.Database.GetOrm()
	if err != nil {
		glog.Errorf("获取数据库连接失败: %v", err)
		return err
	}

	TradeNo := transaction.OutTradeNo
	orderModel := orders.Orders{TradeNo: TradeNo}
	if err := orderModel.FindByTradeNo(db); err != nil {
		glog.Errorf("查询订单失败: %v", err)
		return err
	}
	err = db.Transaction(func(tx *gorm.DB) error {
		switch transaction.TradeStatus {
		case alipay.TradeStatusSuccess, alipay.TradeStatusFinished:
			orderModel.Status = int(orders.OrderStatus_Success)
		case alipay.TradeStatusClosed:
			orderModel.Status = int(orders.OrderStatus_Cancel)
		case alipay.TradeStatusWaitBuyerPay:
			orderModel.Status = int(orders.OrderStatus_Pending)
		}
		t, err := time.Parse(time.RFC3339, transaction.GmtPayment)
		if err != nil {
			fmt.Println("解析失败:", err)

		}
		orderModel.PayTime = t
		orderModel.ActualAmount, _ = strconv.ParseFloat(transaction.TotalAmount, 64)
		orderModel.CallbackTime = time.Now()
		orderModel.CallbackContent = string(transactionJson)
		orderModel.TransactionId = transaction.TradeNo
		err = orderModel.Update(tx)
		if err != nil {
			glog.Errorf("更新订单失败: %v", err)
			return err
		}
		paymentTransaction := &orders.PaymentTransactions{
			OrderId:       orderModel.Id,
			TransactionId: transaction.TradeNo,
			PaymentSource: "alipay",
			Amount:        orderModel.Amount,
			OrderType:     int(orderModel.OrderType),
			CallbackTime:  t,
			CallbackData:  string(transactionJson),
			UserId:        orderModel.UserId,
			CreatedAt:     time.Now(),
			TradeNo:       orderModel.TradeNo,
			//UpdatedAt: time.Now(),
		}
		if err := paymentTransaction.Create(tx); err != nil {
			glog.Errorf("create payment transaction failed:err %v", err)
			return err
		}
		switch orderModel.OrderType {
		case int(orders.OrderTypeRecharge):
			//更新用户余额
			fmt.Println("OrderTypeRecharge start")
			userModel := user.User{UserID: orderModel.UserId}
			err = userModel.IncreseBalance(db, orderModel.UserId, orderModel.Amount)
			if err != nil {
				glog.Errorf("increase balance failed:err %v", err)
				return err
			}
			accountTransactionModel := orders.AccountTransactions{
				UserId:      orderModel.UserId,
				Amount:      orderModel.Amount,
				Description: "充值",
				Type:        orders.AccountTransactionsTypeRecharge,
				CreatedAt:   time.Now(),
			}
			err = accountTransactionModel.Create(db)
			fmt.Println("OrderTypeRecharge down")
			if err != nil {
				glog.Errorf("create account transaction failed:err %v", err)
				return err
			}
		case int(orders.OrderTypeInstance):
			packageInfo := products.ProductPackages{Id: orderModel.PackageId}
			err = packageInfo.GetById(db)
			if err != nil {
				glog.Errorf("get product package info failed:err %v", err)
				return err
			}
			instanceModel := resources.InstanceUses{OrderId: orderModel.Id}
			instanceList, err := instanceModel.GetListByOrderId(tx)
			if err != nil {
				glog.Errorf("get instance use list failed:err %v", err)
				return err
			}
			productModel := products.Products{Id: packageInfo.ProductId}
			err = productModel.GetById(tx)
			if err != nil {
				glog.Errorf("get product info failed:err %v", err)
				return err
			}
			for _, instance := range instanceList {
				instanceModel := &instance
				instanceModel.Status = int(resources.InstanceUseStatusUsing)
				instanceModel.StartTime = time.Now()
				instanceModel.ExpireTime = time.Now().AddDate(0, 0, packageInfo.Duration)
				instanceModel.InstanceName = "云机" + strconv.FormatInt(instanceModel.Id, 10)
				err = instanceModel.Update(tx)
				if err != nil {
					glog.Errorf("update instance use failed:err %v", err)
					return err
				}
				if productModel.Type == 1 {
					go func(id int64) {
						if err := realphone.EasyToRecreateNewInstance(id, instanceModel.UserId); err != nil {
							glog.Error(err)
						}
					}(instance.Id)
				} else {
					instancesModel := resources.Instances{Id: instance.InstanceId}
					err = instancesModel.GetById(tx)
					if err != nil {
						glog.Errorf("get instance failed:err %v", err)
					}
					if instancesModel.AdiTemplateId == 0 {
						instancesModel.AdiTemplateId = 36
					}
					go func(id int64) {
						if err := realphone.ChangeRealPhoneModelAndClearData(id, instancesModel.AdiTemplateId, orderModel.UserId); err != nil {
							glog.Error(err)
						}
					}(instance.Id)
				}
			}

			//TODO:升级实例镜像
			go instances.InstanceConnect(instanceList)
		case int(orders.OrderTypeRenew):
			packageInfo := products.ProductPackages{Id: orderModel.PackageId}
			err = packageInfo.GetById(db)
			if err != nil {
				glog.Errorf("get product package info failed:err %v", err)
				return err
			}
			instanceModel := resources.InstanceUses{OrderId: orderModel.Id}
			instanceList, err := instanceModel.GetListByOrderId(tx)
			if err != nil {
				glog.Errorf("get instance use list failed:err %v", err)
				return err
			}
			for _, instance := range instanceList {
				instanceModel := &instance
				instanceModel.Status = int(resources.InstanceUseStatusUsing)
				err = instanceModel.Update(tx)
				if err != nil {
					glog.Errorf("update instance use failed:err %v", err)
					return err
				}
				if instance.PrewInstanceId > 0 {
					prewInstanceModel := resources.InstanceUses{Id: instance.PrewInstanceId}
					err = prewInstanceModel.UpdatePartFields(tx, map[string]interface{}{"status": int(resources.InstanceUseStatusExpired)})
					if err != nil {
						glog.Errorf("update instance use failed:err %v", err)
						return err
					}
				}
			}
		}

		return nil
	})
	if err != nil {
		glog.Errorf("transaction failed:err %v", err)
		return err
	}
	return nil
}
